package com.block.source.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.block.common.enums.InfoTypeEnum;
import com.block.common.enums.ProfitSharingEnum;
import com.block.common.exception.NotifyExceptionService;
import com.block.common.service.LogFactory;
import com.block.datapush.common.model.result.FilterHandlerResult;
import com.block.datapush.common.service.ISpecialDataFilterHandlerService;
import com.block.datapush.model.result.SpePushResut;
import com.block.datapush.service.IMemberPushOrderInfoService;
import com.block.datapush.special.service.ISpecialCostomInfoService;
import com.block.datapush.special.service.ISpecialDataApiInfoService;
import com.block.db.entity.*;
import com.block.db.mapper.SpecialCostomItemInfoMapper;
import com.block.source.model.dto.SourceMatchResultDTO;
import com.block.source.model.dto.SourceRegisterResultDTO;
import com.block.source.service.ISourceMatchHandleService;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

@Service
public class SourceMatchHandleService implements ISourceMatchHandleService {

    private static final Logger log = LogFactory.getSourceLog();

    @Autowired
    NotifyExceptionService notifyExceptionService;
    @Autowired
    ISpecialCostomInfoService specialCostomInfoService;
    @Autowired
    ISpecialDataApiInfoService specialDataApiInfoService;
    @Resource
    SpecialCostomItemInfoMapper specialCostomItemInfoMapper;
    @Autowired
    ISpecialDataFilterHandlerService specialDataFilterHandlerService;
    @Autowired
    IMemberPushOrderInfoService memberPushOrderInfoService;

    /**
     * 临时数据撞库
     */
    @Override
    public SourceMatchResultDTO toMatchMerchant2(SourceBaseInfo sourceBaseInfo, SourceMemberDataInfoTemp dataInfoTemp) throws InterruptedException {

        // dataInfoTemp 转 memberSourceInfo
        MemberExtInfo memberExtInfo = new MemberExtInfo();
        BeanUtil.copyProperties(dataInfoTemp, memberExtInfo);
        memberExtInfo.setReqIp(dataInfoTemp.getUserIp());
        memberExtInfo.setUsername(dataInfoTemp.getRealName());

        List<SpecialCostomItemInfo> resultTaskList = new ArrayList<>();
        Set<Long> canMatchMerchantSet = new HashSet<>();// 过滤同一个商户的作用

        //  2023/12/27 根据 sourceBaseInfo
        // priceAmount priceRate 计算起推价格
        // 起推价格为0时。设置溢价率为0
        BigDecimal startPriceAmount = sourceBaseInfo.getPriceAmount().multiply(sourceBaseInfo.getPriceRate());

        // 根据渠道的类型，查询不同的商户类型
        // 价格倒序排列(只查询 crm 和 api)
        List<SpecialCostomItemInfo> taskInfoList = new ArrayList<>();
        if (ProfitSharingEnum.FIXEDPRICE.getValue().equals(sourceBaseInfo.getPriceType())){
            //固定价格渠道只能推送给  固定价格的机构
            taskInfoList = specialCostomItemInfoMapper.getSourceFixedTaskList(startPriceAmount);
        }else if(ProfitSharingEnum.PROFITPRICE.getValue().equals(sourceBaseInfo.getPriceType())){

            // 渠道如果是分润的话，则可以推送给所有的机构
            taskInfoList = specialCostomItemInfoMapper.getSourceProfitTaskList(startPriceAmount);
            // SpecialCostomItemInfo specialCostomItemInfo = specialCostomItemInfoMapper.selectById(601L);
            // taskInfoList = Collections.singletonList(specialCostomItemInfo);
        }
        log.info("【商户任务过滤】查询的任务数量【size】{}", taskInfoList.size());

        // 机构任务过滤，筛选可推送的任务
        for (SpecialCostomItemInfo costomItemInfo : taskInfoList) {
            try {
                // TODO: 2024/8/20 检测
                FilterHandlerResult filterResult = specialDataFilterHandlerService.execCondiFilter(costomItemInfo, memberExtInfo);
                log.info("【商户任务过滤】过滤结束【taskId】{}【uid】{}【filterResult】{}",
                        costomItemInfo.getId(), memberExtInfo.getUid(), JSON.toJSONString(filterResult));
                // 过滤成功，且拿到价格最高的推送任务（同一个商户）
                if (filterResult.isSuccess() && !canMatchMerchantSet.contains(costomItemInfo.getInfoId())){
                    canMatchMerchantSet.add(costomItemInfo.getInfoId());
                    resultTaskList.add(costomItemInfo);
                }
            } catch (Exception exception){
                log.error("商户任务过滤异常:", exception);
            }
        }

        log.info("【商户任务过滤】任务过滤之后，可推送任务数量【size】{}", resultTaskList.size());

        CountDownLatch countDownLatch = new CountDownLatch(resultTaskList.size());

        // 异步执行下游机构撞库
        List<Future<SpePushResut>> futureList = new ArrayList<>();
        for (SpecialCostomItemInfo costomItemInfo : resultTaskList) {
            try {
                Future<SpePushResut> merchantInfoFuture = ThreadUtil.execAsync(() -> {
                    SpePushResut spePushResut = new SpePushResut();
                    spePushResut.setPushSuccess(false);
                    try {
                        spePushResut = specialCostomInfoService.checkUser(costomItemInfo, memberExtInfo);
                    }finally {
                        countDownLatch.countDown();
                    }
                    return spePushResut;
                });
                futureList.add(merchantInfoFuture);
            } catch (Exception exception){
                log.error("任务ID:{} 撞库异常, error:{}", costomItemInfo.getId(), exception);
            }
//            finally {
//                countDownLatch.countDown();
//            }
        }

        // 系统等待时间（下游必须在2s内返回）
        countDownLatch.await(5, TimeUnit.SECONDS);

        SpePushResut resultInfo = null;
        List<SpePushResut> spePushResutList = new ArrayList<>();
        for (Future<SpePushResut> spePushResutFuture : futureList) {
            // 抛出异常 isDone()依然为true, 此时get()方法是获取不到数据的, 需添加try catch
            if (spePushResutFuture.isDone()){
                try {
                    SpePushResut spePushResut = spePushResutFuture.get();
                    if (spePushResut.isPushSuccess()){
                        spePushResutList.add(spePushResut);
                    }
                } catch (Exception exception) {
                    log.error("uid:{} 获取撞库结果异常", memberExtInfo.getUid());
                }
            }
        }
        if (CollectionUtil.isNotEmpty(spePushResutList)) {
            Collections.sort(spePushResutList, Comparator.comparing(SpePushResut::getPriceAmount).reversed());
            resultInfo = spePushResutList.get(0);
        }
        SourceMatchResultDTO resultDTO = new SourceMatchResultDTO();
        resultDTO.setSuccess(false);

        if (ObjectUtil.isNotEmpty(resultInfo)){
            // 撞库通过，生成订单信息
            resultDTO.setSuccess(resultInfo.isPushSuccess());
            MemberPushOrderInfo pushOrderInfo = resultInfo.getPushOrderInfo();

            resultDTO.setOrderNo(String.valueOf(pushOrderInfo.getId()));
            resultDTO.setPushOrderInfo(pushOrderInfo);

            resultDTO.setInfoId(resultInfo.getInfoId());
            resultDTO.setInfoName(resultInfo.getInfoName());
            resultDTO.setInfoType(resultInfo.getInfoType());
            resultDTO.setTaskId(resultInfo.getItemInfoId());
            resultDTO.setPriceAmount(resultInfo.getPriceAmount());
        }

        return resultDTO;
    }

    /**
     * 推送用户注册信息
     *
     * @param resultDTO
     * @return
     */
    @Override
    public SourceRegisterResultDTO handleRegisterUser(SourceBaseInfo sourceBaseInfo, SourceMatchResultDTO resultDTO, MemberExtInfo memberExtInfo){

        SourceRegisterResultDTO registerResultDTO = new SourceRegisterResultDTO();
        registerResultDTO.setSuccess(true);
        try {

            MemberPushOrderInfo pushOrderInfo = memberPushOrderInfoService.getById(resultDTO.getOrderNo());

            MemberPushOrderInfo updateOrder = new MemberPushOrderInfo();
            updateOrder.setId(pushOrderInfo.getId());
            updateOrder.setUid(memberExtInfo.getUid());
            memberPushOrderInfoService.updateById(updateOrder);

             //机构类型
            if (!StrUtil.equals(pushOrderInfo.getInfoType(), InfoTypeEnum.CRM.getValue())){
                SpecialDataApiInfo dataPushInfo = new SpecialDataApiInfo();
                dataPushInfo.setId(Long.valueOf(pushOrderInfo.getPushId()));
                dataPushInfo.setUid(memberExtInfo.getUid());
                specialDataApiInfoService.updateById(dataPushInfo);
            }

            return registerResultDTO;
        } catch (Exception exception) {
            exception.printStackTrace();
            String message = StrUtil.format("【resultDTO】{}", JSON.toJSONString(resultDTO));
            notifyExceptionService.notifyNoticeInfo("SOURCE_REGISTER_HANDLE", "注册操作异常", message, exception);
        }
        return registerResultDTO;
    }

}
